package d1_stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamTest04 {
    public static void main(String[] args) {
        //目标:Stream流的终结方法。 注意这些终结方法不会再返回,Stream流对象,相当于关闭流
        List<Movie> movies = new ArrayList<>();
        movies.add(new Movie("剑来", 9.9, "陈平安,宁姚"));
        movies.add(new Movie("遮天", 9.2, "姬紫月,叶凡"));
        movies.add(new Movie("牧神记", 9.3, "秦牧"));
        movies.add(new Movie("凡人修仙传", 9.4, "韩立"));
        movies.add(new Movie("凡人修仙传", 9.4, "韩立"));
        //void forEach(Consumer action) 对此流运算后的元素执行遍历
        //1、进行遍历 forEach
//        movies.stream().forEach(System.out::println);
        movies.stream().forEach(System.out::println);

        //2、计算流运算后的个数
        //long count();
        long count = movies.stream().skip(2).count();
        System.out.println(count);//3
        //3、取最大值
        //封装成Optional<T> --->是为了避免空指针异常,null就会提醒你
        Optional<Movie> max = movies.stream().max(((o1, o2) -> Double.compare(o1.getScore(), o2.getScore())));
        Movie movie1 = max.get();
        System.out.println(movie1);

        //简化-->这个取去最大最小值,可以避免遍历数据,进行一个一个寻找, 开发中很多时候会取最大与最小值
        Movie movie = movies.stream().max(Movie::compareTo).get();
        System.out.println(movie);

        //取最小值
        Optional<Movie> min = movies.stream().min(((o1, o2) -> Double.compare(o1.getScore(), o2.getScore())));
        Movie movie2 = min.get();
        System.out.println(movie2);

        //简化
        Movie movie3 = movies.stream().min(Movie::compareTo).get();
        System.out.println(movie3);

        //4、收集Stream流: 把流中的数据恢复到集合或者数组中去
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        list.add("张三丰");
        Stream<String> stream1 = list.stream(); // 流只能用一次 因为指针已经到了尾部 -->无法回退
        //原理:就是我们这个collect方法的底层会做什么事情？它会去遍历，是不是这个流上的每个数据啊？
        //它每遍历一个数据，它就把它扔到哪里去，扔到底层的ArrayList集合里去，再把这个集合是不是返回给我们，
        //注意: 如果只是调用toList() 集合是不可变的(集合不可修改), 且在jdk16开始[必须高考的分数,就没必要改]
        //                                                                                          底层new 的是ArrayList对象
        List<String> newList = stream1.filter(s -> s.startsWith("张")
                && s.length() == 3).collect(Collectors.toList());
        System.out.println(newList);

        //收集Set集合
        Stream<String> stream2 = list.stream(); // 流只能用一次 因为指针已经到了尾部 -->无法回退
        Set<String> newSet = stream2.filter(s -> s.startsWith("张")
                && s.length() == 3).collect(Collectors.toSet());
        System.out.println(newSet);
//-----------------------------------------------------------------------------------------
        //典型的例子
        Object[] objects = Stream.of("陈", 16, '小', true).toArray();
        System.out.println(Arrays.toString(objects));
        //--------------------------------------------------------------------------
        //收集到数组  数组是强类型(就是固定死的)  集合是泛化的,最后还是Object(可以翻墙)
        Stream<String> stream3 = list.stream(); // 流只能用一次 因为指针已经到了尾部 -->无法回退
        Object[] object = stream3.filter(s -> s.startsWith("张") && s.length() == 3).toArray();
        System.out.println(Arrays.toString(object));

        //收集到Map集合
        List<Movie> movies1 = new ArrayList<>();
        movies1.add(new Movie("剑来", 9.9, "陈平安,宁姚"));
        movies1.add(new Movie("遮天", 9.2, "姬紫月,叶凡"));
        movies1.add(new Movie("牧神记", 9.3, "秦牧"));
        movies1.add(new Movie("凡人修仙传", 9.4, "韩立"));
        movies1.add(new Movie("凡人修仙传", 9.4, "韩立"));

        //先告诉idea, 你要收集的集合,提示就会很强--->直接记忆这行代码
                                                            //需要一个键的映射,需要一个值的映射                                         就是二选一
        Map<String, Double> map = movies1.stream().limit(5).collect(Collectors.toMap(s -> s.getName(), s-> s.getScore(), (v1,v2)->v1));
        Map<Double, String> collect = movies1.stream().limit(5).collect(Collectors.toMap(s -> s.getScore(), s -> s.getName(), (v1, v2) -> v1));
        System.out.println(collect);
        //键不能重复
        //加一个匿名内部类,进行选择一个,就是二分操作, 二选一
        System.out.println(map);
    }
}
